﻿using Microsoft.Kinect;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Speech.AudioFormat;
using Microsoft.Speech.Recognition;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using KinectWindows;

namespace NuiDicomPlayer.Nui.Speech
{
    

    public class SpeechCommander : IDisposable
    {

        public event EventHandler<SpeechRecogised> OnSpeechRecognised;
        private  RecognizerInfo recognizerInfo;
        private KinectSensor Sensor;
         Microsoft.Speech.Recognition.SpeechRecognitionEngine _recognizer=null;


         public void Run(KinectSensor sensor)
         {
             Thread th = new Thread(new ThreadStart(Start));
             Sensor = sensor;
            th.Start();
         }

        private void Start()
        {
            try
            {
                this.recognizerInfo = GetKinectRecognizer();
                _recognizer = new Microsoft.Speech.Recognition.SpeechRecognitionEngine(this.recognizerInfo.Id);
             


               

                GrammarBuilder gb = new GrammarBuilder();
                gb.Culture = this.recognizerInfo.Culture;

                Choices ch = new Choices();
                ch.Add("Shadow on");
                ch.Add("Shadow off");
                ch.Add("New file");
                ch.Add("Informations");
                ch.Add("Dismiss");               
                ch.Add("Sagital");
                ch.Add("Axial");
                ch.Add("Coronal");
                ch.Add("Change brightness");
                ch.Add("Change contrast");
                ch.Add("Zoom all");
                ch.Add("Zoom");
                ch.Add("Quit");
                ch.Add("Close");
                gb.Append(ch);
                Grammar g = new Grammar(gb);
                g.Name="vtk";
                _recognizer.LoadGrammar(g);


                 Sensor.AudioSource.AutomaticGainControlEnabled = false;
                Sensor.AudioSource.BeamAngleMode = BeamAngleMode.Adaptive;
                  Sensor.AudioSource.EchoCancellationMode = EchoCancellationMode.None;
                  Sensor.AudioSource.NoiseSuppression = true;


               
                _recognizer.LoadGrammarCompleted += _recognizer_LoadGrammarCompleted;
                _recognizer.SpeechDetected += _recognizer_SpeechDetected;
                _recognizer.SpeechRecognitionRejected += _recognizer_SpeechRecognitionRejected;
                
                Enabled = true;
                using (Stream Astream = Sensor.AudioSource.Start())
                {
                     _recognizer.SetInputToAudioStream(Astream, new SpeechAudioFormatInfo(EncodingFormat.Pcm, 16000, 16, 1, 32000, 2, null));
                     while (Enabled)
                     {
                         try
                         {
                             RecognitionResult result = _recognizer.Recognize();
                             if (result != null && result.Confidence > 0.7) this.OnSpeechRecognised(this, new SpeechRecogised(result));
                         }
                         catch (Exception err)
                         {
                         }
                     }
                }
                
            }
            catch (Exception err)
            {

            } 
        }

        void _recognizer_LoadGrammarCompleted(object sender, LoadGrammarCompletedEventArgs e)
        {
            
        }

        void _recognizer_SpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e)
        {
            
        }

        void _recognizer_SpeechDetected(object sender, SpeechDetectedEventArgs e)
        {
            
        }

        private static RecognizerInfo GetKinectRecognizer()
        {
            // Check for the Kinect language recognizer for a particular culture and return it.
            Func<RecognizerInfo, bool> matchingFunc = r =>
            {
                string value;
                r.AdditionalInfo.TryGetValue("Kinect", out value);
                return
                    "True".Equals(value, StringComparison.OrdinalIgnoreCase)
                    && "en-US".Equals(r.Culture.Name, StringComparison.OrdinalIgnoreCase);
            };
            return SpeechRecognitionEngine.InstalledRecognizers().Where(matchingFunc).FirstOrDefault();
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (disposing)
            {
                KinectSensor.KinectSensors[App.ActiveSensor].AudioSource.Stop();

                if (_recognizer != null)
                {
                    _recognizer.RecognizeAsyncCancel();
                    _recognizer = null;
                }
            }
        }

        public bool Enabled { get; set; }

        internal void Stop()
        {
            Enabled = false;
            Dispose();
        }
    }

   
}
